package com.baiyang.server.filter;

import java.io.IOException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.baiyang.server.config.provider.MyUsernamePasswordAuthenticationToken;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 该过滤器是开始进行主体认证的
 * -------------------------------------
 * UsernamePasswordAuthenticationFilter讲解：
 * attemptAuthentication方法为数据准备过程
 * UsernamePasswordAuthenticationFilter会调用getAuthenticationManager().authenticate(authRequest)进行对authRequest的验证
 * 如果想要使用该过滤器则需要HttpSecurity配置该bean到UsernamePasswordAuthenticationFilter过滤器的位置
 * -------------------------------------
 * @author XVX
 *
 */
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
	private static final String VER_CODE = "verCode";
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (request.getMethod().equals("POST")&&MediaType.APPLICATION_JSON_VALUE.equals(request.getContentType())) {
			String username = null;
			String password = null;
			String verCode = null;
			try {
				// 获取请求输入流信息，并将它转化为Map类型
				Map<?, ?> map = new ObjectMapper().readValue(request.getInputStream(), Map.class);
				username = String.valueOf(map.get(SPRING_SECURITY_FORM_USERNAME_KEY));
				password = String.valueOf(map.get(SPRING_SECURITY_FORM_PASSWORD_KEY));
				verCode = String.valueOf(map.get(VER_CODE));
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (username == null) {
				username = "";
			}
			if (password == null) {
				password = "";
			}
			username = username.trim();
			MyUsernamePasswordAuthenticationToken authRequest = new MyUsernamePasswordAuthenticationToken(
					username, password,verCode);
			// Allow subclasses to set the "details" property
			setDetails(request, authRequest);	
			return this.getAuthenticationManager().authenticate(authRequest);
		}else {
			return super.attemptAuthentication(request, response);
		}
		
	}
	/**
	 * 设置主体携带信息
	 * 方法讲解：
	 * ---------------------------------
	 * 对主体设置自定义的携带信息
	 * 信息来源通过authenticationDetailsSource.buildDetails(request)方法获取 ---- WebAuthenticationDetailsSource：默认的是sessionId和IP地址
	 * 可以通过重写AuthenticationDetailsSource的buildDetails方法来实现自定义信息的构建
	 * 
	 * 在使用自定义AuthenticationDetailsSource类的方法时需要HttpSecurity调用formLogin().authenticationDetailsSource(authenticationDetailsSource);方法进行设置
	 * ---------------------------------
	 */
	protected void setDetails(HttpServletRequest request,
			UsernamePasswordAuthenticationToken authRequest) {
		System.out.println(authenticationDetailsSource.getClass());
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}
}
